package IC.Parser;

import java_cup.runtime.Symbol;

%%

%class Lexer
%unicode
%public
%function next_token
%type Token
%line
%cup
%scanerror LexicalError

%eofval{
	
	if (yystate() == COMMENT_SLASH_STAR)
		throw new LexicalError("Lexical Error: file ended unexpectedly", yyline, "");
	else
		return new Token(sym.EOF, yyline, "EOF");

%eofval}


%state COMMENT_SLASH_SLASH
%state Whitespace
%state COMMENT_SLASH_STAR


ALPHA=[A-Za-z_] 
UPPER_CASE=[A-Z]
LOWER_CASE=[a-z]
DIGIT=[0-9]
ALPHA_NUMERIC={ALPHA}|{DIGIT}
NUMBER=({DIGIT})+


LineTerminator = \r|\n|\r\n
InputCharacter = [^\r\n]
WhiteSpace     = {LineTerminator} | [ \t\f]

COMMENT_SLASH_SLASH = {EndOfLineComment}

EndOfLineComment     = "//" {InputCharacter}* {LineTerminator}?



%%


{COMMENT_SLASH_SLASH}									{ }									

{WhiteSpace}  											{ }

<YYINITIAL> "/*"										{ yybegin(COMMENT_SLASH_STAR); }

<YYINITIAL> "boolean"									{ return new Token(sym.BOOLEAN,yyline, yytext()); }
<YYINITIAL> "break" 									{ return new Token(sym.BREAK,yyline, yytext()); }
<YYINITIAL> "class"										{ return new Token(sym.CLASS,yyline, yytext()); }

<YYINITIAL> ","											{ return new Token(sym.COMMA,yyline, yytext()); }
<YYINITIAL> "continue"									{ return new Token(sym.CONTINUE,yyline, yytext()); }
<YYINITIAL> "/" 										{ return new Token(sym.DIVIDE,yyline, yytext()); }
<YYINITIAL> "."             							{ return new Token(sym.DOT,yyline, yytext()); }
<YYINITIAL> "=="            							{ return new Token(sym.EQUAL, yyline, yytext()); }
<YYINITIAL> "="											{ return new Token(sym.ASSIGN,yyline, yytext()); }
<YYINITIAL> "extends"		 							{ return new Token(sym.EXTENDS, yyline, yytext()); }
<YYINITIAL> "else"										{ return new Token(sym.ELSE, yyline, yytext()); }
<YYINITIAL> "false"										{ return new Token(sym.FALSE, yyline, yytext()); }
<YYINITIAL> ">="           	 							{ return new Token(sym.GTE, yyline, yytext()); }
<YYINITIAL> ">"            								{ return new Token(sym.GT, yyline, yytext()); }	


<YYINITIAL> "if"              							{ return new Token(sym.IF, yyline, yytext()); }

<YYINITIAL> "int"										{ return new Token(sym.INT, yyline, yytext()); }
<YYINITIAL> "&&"										{ return new Token(sym.LAND, yyline, yytext()); }
<YYINITIAL> "["            	 							{ return new Token(sym.LB, yyline, yytext()); }
<YYINITIAL> "("          	  	 						{ return new Token(sym.LP, yyline, yytext()); }
<YYINITIAL> "{"											{ return new Token(sym.LCBR, yyline, yytext()); }
<YYINITIAL> "length"									{ return new Token(sym.LENGTH, yyline, yytext()); }
<YYINITIAL> "new"										{ return new Token(sym.NEW, yyline, yytext()); }
<YYINITIAL> "!="										{ return new Token(sym.NEQUAL, yyline, yytext()); }
<YYINITIAL> "!"											{ return new Token(sym.LNEG, yyline, yytext()); }
<YYINITIAL> "||"										{ return new Token(sym.LOR, yyline, yytext()); }
<YYINITIAL> "<="           	 							{ return new Token(sym.LTE, yyline, yytext()); }
<YYINITIAL> "<"            	 							{ return new Token(sym.LT, yyline, yytext()); }

<YYINITIAL> "-"											{ return new Token(sym.MINUS, yyline, yytext()); }
<YYINITIAL> "%"											{ return new Token(sym.MOD, yyline, yytext()); }
<YYINITIAL> "*"            								{ return new Token(sym.MULTIPLY, yyline, yytext()); }

<YYINITIAL> "null"										{ return new Token(sym.NULL, yyline, yytext()); }
<YYINITIAL> "+"            								{ return new Token(sym.PLUS, yyline, yytext()); }
<YYINITIAL> "]"           		 						{ return new Token(sym.RB, yyline, yytext()); }
<YYINITIAL> "}"											{ return new Token(sym.RCBR, yyline, yytext()); }
<YYINITIAL> "return"									{ return new Token(sym.RETURN, yyline, yytext()); }
<YYINITIAL> ")"             							{ return new Token(sym.RP, yyline, yytext()); }
<YYINITIAL> ";"             							{ return new Token(sym.SEMI, yyline, yytext()); }
<YYINITIAL> "static"									{ return new Token(sym.STATIC, yyline, yytext()); }
<YYINITIAL> "string"									{ return new Token(sym.STRING, yyline, yytext()); }

<YYINITIAL> "this"										{ return new Token(sym.THIS, yyline, yytext()); }
<YYINITIAL> "true"										{ return new Token(sym.TRUE, yyline, yytext()); }
<YYINITIAL> "void"										{ return new Token(sym.VOID, yyline, yytext()); }
<YYINITIAL> "while"										{ return new Token(sym.WHILE, yyline, yytext()); }

<YYINITIAL> {UPPER_CASE}({ALPHA_NUMERIC})*				{ return new Token(sym.CLASS_ID,yyline, yytext()); }
<YYINITIAL> {LOWER_CASE}({ALPHA_NUMERIC})*				{ return new Token(sym.ID, yyline, yytext()); }

<YYINITIAL>  [\"]({ALPHA_NUMERIC}|[ !#-\[\]-~]|"\\\\"|"\\\""|"\\t"|"\\n")*[\"]			{ return new Token(sym.QUOTE, yyline, yytext()); }

<YYINITIAL> [0]+[1-9]+									{throw new LexicalError("Lexical Error: illegal character", yyline, yytext()); }
<YYINITIAL> ({NUMBER})+ 								{ return new Token(sym.INTEGER, yyline, new Integer(yytext())); }

<YYINITIAL>  . 											{throw new LexicalError("Lexical Error: illegal character", yyline, yytext()); }


<COMMENT_SLASH_STAR> [^*/]		 						{ }
<COMMENT_SLASH_STAR>  "*/"								{ yybegin(YYINITIAL); }	
<COMMENT_SLASH_STAR>  "*"		 						{ }







